package cn.well.cloud.exception.aop;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ibatis.javassist.ClassClassPath;
import org.apache.ibatis.javassist.ClassPool;
import org.apache.ibatis.javassist.CtClass;
import org.apache.ibatis.javassist.CtMethod;
import org.apache.ibatis.javassist.Modifier;
import org.apache.ibatis.javassist.NotFoundException;
import org.apache.ibatis.javassist.bytecode.CodeAttribute;
import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
import org.apache.ibatis.javassist.bytecode.MethodInfo;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * RequestMapping 日志AOP
 * wison
 * 下午9:13:35
 */
@Aspect
@Component
@Order(1)
public class WebLogAop {
    private Logger log = LoggerFactory.getLogger(this.getClass()); 
    private final ObjectMapper mapper;
   
    @Autowired
    public WebLogAop(ObjectMapper mapper) {
      this.mapper = mapper;
    }
   
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void webLog() {
    }
   
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws ClassNotFoundException, NotFoundException {
        
        String classType = joinPoint.getTarget().getClass().getName();  
        Class<?> clazz = Class.forName(classType);  
        String clazzName = clazz.getName();  
        String methodName = joinPoint.getSignature().getName(); //获取方法名称 
        Object[] args = joinPoint.getArgs();//参数
        //获取注解
        String restName = getRequestMappingValue(this.getClass(), clazzName, methodName);
        //获取参数名称和值
        Map<String,Object > nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,args); 
        log.debug(">>>>>>>>>类："+joinPoint.getTarget().getClass().getName() );
        log.debug(">>>>>>>>>方法："+methodName);
        log.debug(">>>>>>>>>接口："+restName);
        log.debug(">>>>>>>>>参数："+nameAndArgs.toString());
    }
    
    private String getRequestMappingValue(Class cls, String clazzName, String methodName) throws NotFoundException, ClassNotFoundException { 

        ClassPool pool = ClassPool.getDefault();  
        ClassClassPath classPath = new ClassClassPath(cls);  
        pool.insertClassPath(classPath);  
        CtClass cc = pool.get(clazzName);  
        //得到requestMapping注释
        CtMethod cm = cc.getDeclaredMethod(methodName);  
        RequestMapping annotation = (RequestMapping) cm.getAnnotation(RequestMapping.class);
        String name = annotation.name();
        log.info(name);
        String result = "";
        String[] value = annotation.value();
        for (String string2 : value){
            result += string2;
        }
        return result;  
    }
    
    private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException { 
        Map<String,Object > map=new HashMap<String,Object>();

        ClassPool pool = ClassPool.getDefault();  
        ClassClassPath classPath = new ClassClassPath(cls);  
        pool.insertClassPath(classPath);  
          
        CtClass cc = pool.get(clazzName);  
        CtMethod cm = cc.getDeclaredMethod(methodName);  
        // 使用javaassist的反射方法获取方法的参数名
        MethodInfo methodInfo = cm.getMethodInfo();
        CodeAttribute codeAttribute = methodInfo.getCodeAttribute();  
        LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);  
        if (attr == null) {  
            // exception  
        }  
       // String[] paramNames = new String[cm.getParameterTypes().length];  
        int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;  
        for (int i = 0; i < cm.getParameterTypes().length; i++){  
            map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名  
        }  
        
        //Map<>
        return map;  
    }
}

